import { useCallback, useRef, TouchEvent, MouseEvent } from 'react';

interface UseLongPressOptions {
  onLongPress: (event?: TouchEvent | MouseEvent) => void;
  onClick?: (event?: TouchEvent | MouseEvent) => void;
  delay?: number; // 长按触发延迟（毫秒）
  shouldPreventDefault?: boolean;
}

interface LongPressHandlers {
  onMouseDown: (event: MouseEvent) => void;
  onMouseUp: (event: MouseEvent) => void;
  onMouseLeave: (event: MouseEvent) => void;
  onTouchStart: (event: TouchEvent) => void;
  onTouchEnd: (event: TouchEvent) => void;
}

/**
 * 长按检测 Hook
 *
 * 用法:
 * ```tsx
 * const longPressHandlers = useLongPress({
 *   onLongPress: () => {
 *     console.log('Long pressed!');
 *   },
 *   onClick: () => {
 *     console.log('Clicked!');
 *   },
 *   delay: 500,
 * });
 *
 * <div {...longPressHandlers}>Press me</div>
 * ```
 */
export const useLongPress = ({
  onLongPress,
  onClick,
  delay = 500,
  shouldPreventDefault = true,
}: UseLongPressOptions): LongPressHandlers => {
  const timerRef = useRef<NodeJS.Timeout | null>(null);
  const isLongPressRef = useRef(false);
  const eventRef = useRef<TouchEvent | MouseEvent | null>(null);

  const start = useCallback((event: TouchEvent | MouseEvent) => {
    if (shouldPreventDefault && event.target) {
      // 阻止默认行为（如文本选择）
      event.preventDefault();
    }

    eventRef.current = event;
    isLongPressRef.current = false;

    timerRef.current = setTimeout(() => {
      isLongPressRef.current = true;
      onLongPress(eventRef.current || undefined);
    }, delay);
  }, [onLongPress, delay, shouldPreventDefault]);

  const clear = useCallback((event: TouchEvent | MouseEvent, shouldTriggerClick = true) => {
    if (timerRef.current) {
      clearTimeout(timerRef.current);
      timerRef.current = null;
    }

    // 如果不是长按，且有onClick回调，则触发点击
    if (shouldTriggerClick && !isLongPressRef.current && onClick) {
      onClick(event);
    }

    isLongPressRef.current = false;
    eventRef.current = null;
  }, [onClick]);

  const onMouseDown = useCallback((event: MouseEvent) => {
    start(event);
  }, [start]);

  const onMouseUp = useCallback((event: MouseEvent) => {
    clear(event);
  }, [clear]);

  const onMouseLeave = useCallback((event: MouseEvent) => {
    clear(event, false);
  }, [clear]);

  const onTouchStart = useCallback((event: TouchEvent) => {
    start(event);
  }, [start]);

  const onTouchEnd = useCallback((event: TouchEvent) => {
    clear(event);
  }, [clear]);

  return {
    onMouseDown,
    onMouseUp,
    onMouseLeave,
    onTouchStart,
    onTouchEnd,
  };
};
